/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import controlador.GestorDeDibuix;
import java.util.ConcurrentModificationException;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Observable;
import sprites.*;
import vista.ZonaDeJoc;

/**
 *
 * @author PA
 * @version 2010
 */
public class ModelJoc extends Observable {
    //private LinkedList vEntes = new LinkedList(); // Elements a visualitzar

    private LinkedList<Sprite> vEntes = new LinkedList<Sprite>(); // Elements a visualitzar
    // Patró Singleton
    private static ModelJoc instancia = new ModelJoc();
    private int marcadorValor = 0;
    private boolean over = false;
    private boolean fail = false;
    private int totalBullets = 0;
    private int totalAbatidos = 0;

    private ModelJoc() {
    }

    public static ModelJoc getInstancia() {
        return instancia;
    }

    // Fi patró Singleton
    public void iniciarJoc() {
        afegirElement(new Fons(ZonaDeJoc.pantalla));
        afegirElement(new GimberBoy(ZonaDeJoc.pantalla));
        afegirElement(new EsferaR(ZonaDeJoc.pantalla));
        afegirElement(new EsferaL(ZonaDeJoc.pantalla));
        afegirElement(new NauEnemiga(ZonaDeJoc.pantalla));

        setChanged();
    }

    public void afegirElement(Sprite b) {
        vEntes.add(b);
        setChanged();
    }

    public void eliminarElement(Sprite b) {
        vEntes.remove(b);
        setChanged();
    }

    public void collisionGestor() {

        Sprite s;
        ListIterator<Sprite> iter = vEntes.listIterator(0);
//        LinkedList collisionList = new LinkedList();
        try {
            while (iter.hasNext()) {

                s = iter.next();

                if (s instanceof PlayableElement) {

                    ListIterator<Sprite> iterColision = vEntes.listIterator(0);
                    while (iterColision.hasNext()) {

                        Sprite sCol = iterColision.next();
                        if (sCol instanceof PlayableElement) {
                            ((PlayableElement) s).collision((PlayableElement) sCol);
                        }
                    }

//                    collisionList.add(s);
                }
            }
            setChanged();
        } catch (ConcurrentModificationException e) {
        }
    }

    public void animar() {
        Sprite s;
        //ListIterator iter = vEntes.listIterator(0);
        ListIterator<Sprite> iter = vEntes.listIterator(0);
        try {
            while (iter.hasNext()) {
                //s = (Sprite) iter.next();
                s = iter.next();
                s.animar();
            }
            setChanged();
        } catch (ConcurrentModificationException e) {
        }
        this.collisionGestor();
        this.cleanDeads();
    }

    public Sprite getSprite(int n) {
        //return (Sprite) (vEntes.get(n));
        return vEntes.get(n);
    }

    public void pintar() {
        Sprite s;
        //ListIterator iter = vEntes.listIterator(0);
        ListIterator<Sprite> iter = vEntes.listIterator(0);
        try {
            while (iter.hasNext()) {
                //s = (Sprite) iter.next();
                s = iter.next();
                s.pintar();
            }
            setChanged();
        } catch (ConcurrentModificationException e) {
        }

        GimberBoy navePrincipal = null;
        try {
            navePrincipal = (GimberBoy) this.getSprite(1);
            GestorDeDibuix.getInstancia().pintarTexto("Vidas " + navePrincipal.getVides(), 20, 35, 85, 15);
        } catch (Exception e) {
            GestorDeDibuix.getInstancia().pintarTexto("Vidas " + 0, 20, 35, 85, 15);
        }

        if (this.isOver()) {
            String endMsg = this.isFail() ? "¡HAS PERDIDO!" : "¡HAS GANADO!";
            GestorDeDibuix.getInstancia().pintarTexto(endMsg, 350, 300, 97, 20);
        }

        GestorDeDibuix.getInstancia().pintarTexto("Puntuación " + this.getMarcadorValor(), 20, 50, 85, 15);
        GestorDeDibuix.getInstancia().pintarTexto("Abaditos " + this.getTotalAbatidos(), 20, 65, 85, 15);

        try {
            totalBullets = navePrincipal.getBulletCount();
        } catch (Exception e) {
//            System.out.println(e);
        }
        GestorDeDibuix.getInstancia().pintarTexto("Disparos " + totalBullets, 20, 20, 85, 15);

    }

    private void cleanDeads() {

        Sprite s;
        ListIterator<Sprite> iter = vEntes.listIterator(0);
        LinkedList<Sprite> vEntesVivos = new LinkedList<Sprite>();
        boolean quedanEnemigos = false;

        try {

            while (iter.hasNext()) {

                s = iter.next();



                if (!(s instanceof PlayableElement) || (s instanceof PlayableElement && !((PlayableElement) s).isDead())) {

                    vEntesVivos.add(s);
                    if (!quedanEnemigos) {
                        quedanEnemigos = isPersonajeEnemigo(s);
                    }

                } else {

                    if (isPersonajeEnemigo(s)) {
                        totalAbatidos++;
                    }
                    
                    int oldMarcador = this.marcadorValor;
                    this.marcadorValor += ((PlayableElement) s).getPuntos();

                    if (s instanceof GimberBoy) {
                        this.fail = true;
                        this.over = true;
                    }

                    if (oldMarcador < this.marcadorValor) {
                        System.out.println("TOTAL PUNTOS: " + this.marcadorValor);
                    }

                }
            }
            setChanged();
        } catch (ConcurrentModificationException e) {
        }

        this.over = this.over || !quedanEnemigos;
        vEntes = vEntesVivos;
    }

    public int getMarcadorValor() {
        return marcadorValor;
    }
    public int getTotalAbatidos() {
        return totalAbatidos;
    }

    public boolean isOver() {
        return over;
    }

    public boolean isFail() {
        return fail;
    }

    public boolean isPersonajeEnemigo(Sprite elem) {
        return (elem instanceof NauEnemiga) || (elem instanceof EsferaR) || (elem instanceof EsferaL);
    }
}
